package com.ruoyi.framework.aspectj;

import com.ruoyi.common.annotation.SendEmailWhenException;
import com.ruoyi.common.utils.ExceptionUtil;
import com.ruoyi.common.utils.JavaMailUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.system.domain.SysUser;
import com.ruoyi.system.service.ISysUserService;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 遇到抛出异常时发送邮件框架
 *
 * @author weixin
 */
@Aspect
@Component
public class EmailAspect {
    private static final Logger log = LoggerFactory.getLogger(EmailAspect.class);

    @Autowired
    private ISysUserService userService;

    // 配置织入点
    @Pointcut("@annotation(com.ruoyi.common.annotation.SendEmailWhenException)")
    public void sendEmailWhenExceptionPointCut() {
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint 切点
     * @param e         异常
     */
    @AfterThrowing(value = "sendEmailWhenExceptionPointCut()", throwing = "e")
    public void doAfterSendEmailWhenExceptionPointCut(JoinPoint joinPoint, Exception e) {
        handleLog(joinPoint, e);
    }

    protected void handleLog(final JoinPoint joinPoint, final Exception e) {
        try {
            // 获得注解
            SendEmailWhenException sendEmailWhenException = getAnnotationLog(joinPoint);
            if (sendEmailWhenException == null) {
                return;
            }

            // 获取当前的用户，用于发送邮件
            SysUser currentUser = userService.selectUserByLoginName("admin");

            if (currentUser == null) {
                return;
            }

            // 设置邮件标题和内容
            // 根据方法名称、参数值以及异常信息拼装
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] methodArgs = joinPoint.getArgs();//参数
            String emailTitle = sendEmailWhenException.title() + className + "." + methodName + "() failed!";
            StringBuilder emailContent = new StringBuilder();
            emailContent.append("错误位置：<br/>&nbsp;&nbsp;&nbsp;&nbsp;").append(emailTitle).append("<br/>");
            emailContent.append("方法参数：<br/>&nbsp;&nbsp;&nbsp;&nbsp;").append(ArrayUtils.toString(methodArgs)).append("<br/>");
            emailContent.append("异常信息：<br/>").append(StringUtils.replace(ExceptionUtil.getExceptionMessage(e), System.lineSeparator(), "<br/>"));

            log.debug(emailContent.toString());
            // 异步发送邮件
            AsyncManager.me().execute(JavaMailUtils.sendEmailAsync(currentUser.getEmail(), emailTitle, emailContent.toString()));
        } catch (Exception exp) {
            // 记录本地异常日志
            log.error("==异常后发送邮件失败！==");
            log.error("异常信息:{}", ExceptionUtil.getExceptionMessage(exp));
        }
    }


    /**
     * 是否存在注解，如果存在就获取
     */
    private SendEmailWhenException getAnnotationLog(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(SendEmailWhenException.class);
        }
        return null;
    }
}
